package se.ytterman.jserial.framework.device;

import java.lang.*;
import java.util.*;

import javax.xml.xpath.*;

import org.w3c.dom.*;

import se.ytterman.jserial.util.*;

public class RequestFactory {
    
    public RequestFactory(Document requestModelDocument) {
        this.requestModelDocument = requestModelDocument;
    }
    
    public void loadModel() {
        // Disassemble XML dom tree
        try {
            // Extract the events
            XPathFactory xpathFactory = XPathFactory.newInstance();
            XPath eventExtractor = xpathFactory.newXPath();
                    
            // Iterate over found events
            NodeList requestNodes = (NodeList)eventExtractor.evaluate("/Tokens/Requests/*", 
                                                                        this.requestModelDocument, 
                                                                        XPathConstants.NODESET);
 
            for(int i = 0; i < requestNodes.getLength(); i++) {
                // Extract event information
                Element requestNode = (Element)requestNodes.item(i);
                String requestId = requestNode.getAttribute("id");
                String requestName = requestNode.getAttribute("name");
                
                // DEBUG System.out.println("Request: (" + requestId + ") " + requestName);

                NodeList formatNodes = requestNode.getElementsByTagName("RequestFormat");

                for(int j = 0; j < formatNodes.getLength(); j++) {
                    Element formatNode = (Element)formatNodes.item(j);
                             
                    Node formatText = formatNode.getFirstChild();
                    
                    // Fetch text child nodes 
                    String formatString = formatText.getNodeValue();
                    
                    // Print
                    // DEBUG System.out.println("\tFormat: " + formatString);
                }
            }
        }
        catch(Exception e)
        {
        }
     }
    
     public Request newRequest(String requestId, String... parameterValues) {
         // Declare result
         Request requestObject = null;
         
         // Disassemble XML dom tree
        try {
            // Create helper classes...
            XPathFactory xpathFactory = XPathFactory.newInstance();
            XPath eventExtractor = xpathFactory.newXPath();
                    
            // Extract desired request model...
            String xpathString = "/Tokens/Requests/Request[@id='" + requestId + "']";
            NodeList requestNodes = (NodeList)eventExtractor.evaluate(xpathString, 
                                                                      this.requestModelDocument, 
                                                                      XPathConstants.NODESET);
 
            if(requestNodes.getLength() == 1) {
                // Extract event information
                Element requestNode = (Element)requestNodes.item(0);
                String requestName = requestNode.getAttribute("name");                

                // Get request format node    
                NodeList formatNodes = requestNode.getElementsByTagName("RequestFormat");

                if(formatNodes.getLength() == 1) {
                    Element formatNode = (Element)formatNodes.item(0);
                             
                    Node formatText = formatNode.getFirstChild();
                    
                    // Fetch text child nodes 
                    String formatString = formatText.getNodeValue();
                                        
                    requestObject = new Request(requestId, 
                                                requestName, 
                                                formatString);
                    
                    // Extract parameter definitions from XML token definition
                    XPath parameterExtractor = xpathFactory.newXPath();
                
                    String parameterXpath = "/Tokens/Requests/Request[@id='" + requestId + "']" +
                                            "/Parameters/*";
                    
                    NodeList parameterNodes = (NodeList)parameterExtractor.evaluate(parameterXpath, 
                                                                                    this.requestModelDocument, 
                                                                                    XPathConstants.NODESET);
                
                    // Check number of parameters
                    if(parameterValues.length < parameterNodes.getLength()) {
                        throw new Exception("Parameter number mismatch");
                    }
                
                    // Iterate over potential parameter tags...
                    for(int j = 0; j < parameterNodes.getLength(); j++) {
                        // Iterate over parameter tags
                        Element parameterNode = (Element)parameterNodes.item(j);
                    
                        // Extract attributes
                        String parameterType = parameterNode.getAttribute("type");
                        String parameterName = parameterNode.getAttribute("name");
                        
                        // Create constructor parameters (String)
                        String parameterString = parameterValues[j];                                                                    
                        Object[] constructorParameters = new Object[1];
                        constructorParameters[0] = parameterString;
                    
                        // Create parameter object instance
                        Object parameterObject = InstanceFactory.newInstance(parameterType, 
                                                                             constructorParameters, 
                                                                             false);
                    
                        // Add parameter to response object
                        requestObject.addParameter(parameterName, parameterObject);
                    }
                }
                else {
                    // XXX Throw exception
                    System.out.println("APA");
                }
            }
            else {
                System.out.println("BEPA" + requestNodes.getLength());                
            }
        }
        catch(Exception e)
        {
            System.out.println("CEPA");
            e.printStackTrace();
        }
        
        return requestObject;
     }
    
     private Document requestModelDocument;
}
